package com.jqd.framework.util.file;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;

import com.jqd.framework.util.IoUtils;

/**
 * 
 * TODO
 * 
 * @author liaozhicheng@purple-river.com
 * @date 2011-6-18
 * @since 1.0
 */
public class FileUtil {
	
	private FileUtil() {
		
	}
	
	
	/**
	 * 删除某个源目录及其所有子目录下的指定目录或文件 1.不区分删除的是目录还是文件，可同时删除文件和目录 2.采用可变参数形式，可同时删除多个目录或文件，采用
	 * #deleteFileOrDir(sourceDir, dir1, file1, dir2); 3.如果不指定 targets 或者 targets ==
	 * null，则默认删除源目录；即如果需要删除某个目录或文件可使用 {@link #deleteFileOrDir(String)}
	 * 
	 * @param sourceDir
	 *            源目录
	 * @param targets
	 *            需要删除的目录或文件
	 */
	public static void deleteFileOrDir(String sourceDir, String... targets) {
		
		if (StringUtils.isEmpty(sourceDir))
			return;
		
		File source = new File(sourceDir);
		if (!source.exists())
			return;
		
		// 如果不指定目标文件，则默认删除源目录
		if (targets == null || targets.length == 0) {
			FileUtils.deleteQuietly(source);
			return;
		}
		
		delete(source, targets);
	}
	
	
	// 递归删除源目录及其子目录下所有目标目录和文件
	private static void delete(File source, String... targets) {
		
		File[] files = source.listFiles();
		for (File file : files) {
			for (String target : targets) {
				if (StringUtils.isNotEmpty(target) && target.equals(file.getName())) {
					
					FileUtils.deleteQuietly(file);
				}
			}
			
			if (file.isDirectory())
				delete(file, targets);
		}
	}
	
	
	public static void main(String[] args) {
		deleteFileOrDir("G:/temp/moa", ".svn", "vssver2.scc");
	}
	
	
	/**
	 * 将指定路径的文件内容解析为一个字符串
	 * 
	 * @param path
	 *            需要解析的文件路径
	 * @return 以字符串形式返回文件内容
	 */
	public static String getFileCode(String path) {
		StringBuffer buffer = null;
		FileInputStream fileInputStream = null;
		try {
			fileInputStream = new FileInputStream(new File(path));
			byte[] array = new byte[fileInputStream.available()];
			buffer = new StringBuffer();
			while ((fileInputStream.read(array)) != -1) {
				buffer.append(new String(array));
			}
		}
		catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		catch (IOException e) {
			e.printStackTrace();
		}
		finally {
			if (fileInputStream != null) {
				try {
					fileInputStream.close();
				}
				catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return buffer.toString();
	}
	
	
	/**
	 * 通过一个指定的文件路径截取文件名
	 * 
	 * @param path
	 *            文件路径
	 * 
	 * @return 返回文件名
	 */
	public static String interceptFileName(String filePath) {
		String fileName = ""; // 文件名，输出到用户的下载对话框
		// 从文件完整路径中提取文件名，并进行编码转换，防止不能正确显示中文名
		try {
			if (filePath.lastIndexOf("/") > 0) {
				fileName = new String(filePath.substring(filePath.lastIndexOf("/") + 1,
						filePath.length()).getBytes("GB2312"), "ISO8859_1");
			}
			else if (filePath.lastIndexOf("\\") > 0) {
				fileName = new String(filePath.substring(filePath.lastIndexOf("\\") + 1,
						filePath.length()).getBytes("GB2312"), "ISO8859_1");
			}
		}
		catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return fileName;
	}
	
	
	/**
	 * 给定根目录，返回一个相对路径所对应的实际文件名.
	 * 
	 * @param baseDir
	 *            指定根目录
	 * @param absFileName
	 *            相对路径名，来自于ZipEntry中的name
	 * @return java.io.File 实际的文件
	 */
	public static File getRealFileName(String baseDir, String absFileName) {
		// 判断是否有下级目录,如果没有则将该文件直接new出来
		String[] dirs = absFileName.split("/");
		File ret = new File(baseDir);
		if (!ret.exists()) {
			ret.mkdir();
		}
		// 有下级目录则先创建目录，再创建文件
		if (dirs.length > 1) {
			for (int i = 0; i < dirs.length - 1; i++) {
				ret = new File(ret, dirs[i]);
			}
			if (!ret.exists())
				ret.mkdirs();
			ret = new File(ret, dirs[dirs.length - 1]);
			return ret;
		}
		return new File(ret, absFileName);
	}
	
	
	/**
	 * 解压zip文件
	 * 
	 * @param zipFilename
	 * @param dir
	 * @throws Exception
	 */
	public static String upZipFile(String zipFilename, String dir) {
		ZipInputStream zin = null;
		OutputStream os = null;
		String fileName = "";
		try {
			zin = new ZipInputStream(new FileInputStream(zipFilename));
			ZipEntry ze = null;
			byte[] buf = new byte[1024];
			while ((ze = zin.getNextEntry()) != null) {
				if (ze.getName().endsWith(".template.html")) {
					fileName = ze.getName();
					os = new BufferedOutputStream(new FileOutputStream(getRealFileName(dir,
							ze.getName())));
					int readLen = 0;
					while ((readLen = zin.read(buf, 0, 1024)) != -1) {
						os.write(buf, 0, readLen);
					}
				}
			}
		}
		catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		catch (IOException e) {
			e.printStackTrace();
		}
		finally {
			IoUtils.closeSilently(os);
			IoUtils.closeSilently(zin);
		}
		return dir + fileName;
	}
	
}
